package com.nhim.cms.dao;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.orm.jpa.JpaCallback;
import org.springframework.stereotype.Repository;

import com.nhim.cms.domain.CustomWidget;
import com.nhim.core.dao.CoreDAO;


	/**
	 * A data access object (DAO) providing persistence and search support for
	 * ContentType entities. Transaction control of the save(), update() and
	 * delete() operations can directly support Spring container-managed
	 * transactions or they can be augmented to handle user-managed Spring
	 * transactions. Each of these methods provides additional information for how
	 * to configure it for the desired type of transaction control.
	 * 
	 * @see .CustomWidget
	 * @author Huy Lieu Ta
	 */
	@Repository("customWidgetDAO")
	public class CustomWidgetDAO extends CoreDAO<Integer, CustomWidget> implements
			ICustomWidgetDAO {
		
		// property constants
		public static final String DESCRIPTION = "description";
		public static final String NAME = "name";
		public static final String CLASS_NAME = "className";
		
		@Autowired
		EntityManagerFactory entityManagerFactory;

		@PostConstruct
		public void init() {
			super.setEntityManagerFactory(entityManagerFactory);
		}
		
		public static CustomWidgetDAO getFromApplicationContext(ApplicationContext ctx) {
			return (CustomWidgetDAO) ctx.getBean(CustomWidgetDAO.class);
		}

		@Override
		public Integer countCustomWidgetBySearch(final String startsWith) {
			try {
				return getJpaTemplate().execute(new JpaCallback<Integer>() {

					@Override
					public Integer doInJpa(EntityManager em)
							throws PersistenceException {
						Query query = queryCustomWidgetBySearch(em,
								startsWith, null, true);
						return ((Number) query.getSingleResult()).intValue();
					}
				});
			} catch (RuntimeException re) {
				logger.error("countCustomWidgetBySearch failed", re);
				throw re;
			}
		}

		@SuppressWarnings("unchecked")
		@Override
		public List<CustomWidget> findCustomWidgetEntriesBySearch(
				final String startsWith, final String orderBy) {

				try {
					return getJpaTemplate().executeFind(
							new JpaCallback<List<CustomWidget>>() {

								@Override
								public List<CustomWidget> doInJpa(EntityManager em)
										throws PersistenceException {
									Query query = queryCustomWidgetBySearch(em,
											startsWith, orderBy, false);
									return query.getResultList();
								}
							});
				} catch (RuntimeException re) {
					logger.error("findCustomWidgetEntriesBySearch failed", re);
					throw re;
				}
		}
		
		/**
		 * Query for Element Definitions based on the search parameters. If
		 * startsWith is specified, the results will not be ordered.
		 * 
		 * @param startsWith
		 *            the starting string
		 * @param orderBy
		 *            the order of the results
		 * @param isCount
		 *            true to query on the count only
		 * @return the query, or null to return full report count.
		 */
		private Query queryCustomWidgetBySearch(EntityManager em,
				String startsWith, String orderBy, boolean isCount) {
			// Determine which parameters to include.
			boolean isFirstStatement = true;
			boolean hasStartsWith = startsWith != null && startsWith.length() > 0;

			// Construct the query string.
			String retValue = isCount ? "count(o)" : "o";
			String queryString = "select " + retValue + " from CustomWidget o";

			if (hasStartsWith) {
				queryString += isFirstStatement ? " WHERE" : " AND";
				isFirstStatement = false;
				queryString += " o.name >=:startsWith";
				queryString += " AND o.name <=:startsWithZ";
			}
			if (!hasStartsWith && orderBy != null && orderBy.length() >= 0) {
				queryString += " ORDER BY " + orderBy;
			}

			// Construct the query;
			Query query = em.createQuery(queryString);

			if (hasStartsWith) {
				String startsWithLc = startsWith.toLowerCase();
				query.setParameter("startsWith", startsWithLc);
				query.setParameter("startsWithZ", startsWithLc + "zzzzzz");
			}
			return query;
		}

		
}
